package com.jms.tomcat.http;

import com.jms.tomcat.core.JmsServletContext;
import com.jms.tomcat.stream.BfOutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class JmsResponse implements HttpServletResponse {

    private final BfOutputStream bfOutputStream;
    private final PrintWriter bfPrintWriter;
    private final OutputStream socketOutputStream;
    private int status;
    private final JmsServletContext servletContext;
    /**
     * 响应头
     */
    public final Map<String, String> responseHead = new HashMap<>();
    private final Map<String, String> setCookie = new HashMap<>();

    public JmsResponse(OutputStream outputStream, JmsServletContext servletContext) {
        this.servletContext = servletContext;
        status = HttpServletResponse.SC_OK;
        socketOutputStream = outputStream;
        bfOutputStream = new BfOutputStream();
        bfPrintWriter = new PrintWriter(new OutputStreamWriter(bfOutputStream, StandardCharsets.UTF_8));
    }

    @Override
    public void addCookie(Cookie cookie) {
        StringBuilder setCookieValue = new StringBuilder();
        String cookieName = cookie.getName();
        String cookieValue = cookie.getValue();
        if (cookieName != null && cookieValue != null) {
            setCookieValue.append(cookie.getName()).append("=").append(cookie.getValue()).append(";");
            String maxAge = cookie.getMaxAge() + "";
            if (!"".equals(maxAge)) {
                setCookieValue.append("Max-Age=").append(maxAge).append(";");
            }
            String path = cookie.getPath();
            if (path != null && !"".equals(path)) {
                setCookieValue.append("Path=").append(path).append(";");
            }
            String domain = cookie.getDomain();
            if (domain != null && !"".equals(domain)) {
                setCookieValue.append("Domain=").append(domain).append(";");
            }
            if (cookie.getSecure()) {
                setCookieValue.append("Secure=").append(true).append(";");
            }
            if (cookie.isHttpOnly()) {
                setCookieValue.append("HttpOnly=").append(true).append(";");
            }
            String comment = cookie.getComment();
            if (comment != null && !"".equals(comment)) {
                setCookieValue.append("Comment=").append(comment).append(";");
            }
            String version = cookie.getVersion() + "";
            if (!"".equals(version)) {
                setCookieValue.append("Version=").append(version).append(";");
            }
            setCookie.put(cookie.getName(), setCookieValue.toString());
        }
    }

    @Override
    public boolean containsHeader(String name) {
        return false;
    }

    @Override
    public String encodeURL(String url) {
        return null;
    }

    @Override
    public String encodeRedirectURL(String url) {
        return null;
    }

    @Override
    public String encodeUrl(String url) {
        return null;
    }

    @Override
    public String encodeRedirectUrl(String url) {
        return null;
    }

    @Override
    public void sendError(int sc, String msg) {

    }

    @Override
    public void sendError(int sc) {

    }

    @Override
    public void sendRedirect(String location) {
        setStatus(HttpServletResponse.SC_FOUND);
        setHeader("Location", location);
    }

    @Override
    public void setDateHeader(String name, long date) {

    }

    @Override
    public void addDateHeader(String name, long date) {

    }

    @Override
    public void setHeader(String name, String value) {
        responseHead.put(name, value);
    }

    @Override
    public void addHeader(String name, String value) {
        setHeader(name, value);
    }

    @Override
    public void setIntHeader(String name, int value) {

    }

    @Override
    public void addIntHeader(String name, int value) {

    }

    @Override
    public void setStatus(int sc) {
        status = sc;
    }

    @Override
    public void setStatus(int sc, String sm) {

    }

    @Override
    public int getStatus() {
        return status;
    }

    @Override
    public String getHeader(String name) {
        return null;
    }

    @Override
    public Collection<String> getHeaders(String name) {
        return null;
    }

    @Override
    public Collection<String> getHeaderNames() {
        return null;
    }

    @Override
    public String getCharacterEncoding() {
        return null;
    }

    @Override
    public String getContentType() {
        return null;
    }

    @Override
    public ServletOutputStream getOutputStream() {
        return bfOutputStream;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return bfPrintWriter;
    }

    @Override
    public void setCharacterEncoding(String charset) {
        String contentType = getContentType();
        if (contentType != null) {
            if (contentType.contains("charset")) {
                String[] contentTypeArr = contentType.split(";");
                for (int i = 0; i < contentTypeArr.length; i++) {
                    if (contentTypeArr[i].contains("charset")) {
                        contentTypeArr[i] = "charset=" + charset;
                    }
                }
                setContentType(String.join(";", contentTypeArr));
            } else {
                setContentType(contentType + ";charset=" + charset);
            }
        }
    }

    @Override
    public void setContentLength(int len) {

    }

    @Override
    public void setContentLengthLong(long len) {

    }

    @Override
    public void setContentType(String type) {
        setHeader("Content-Type", type);
    }

    @Override
    public void setBufferSize(int size) {

    }

    @Override
    public int getBufferSize() {
        return 0;
    }

    @Override
    public void flushBuffer() throws IOException{
        bfOutputStream.flush();
        //构建响应行
        StringBuilder responseBuild = new StringBuilder("HTTP/1.1 ").append(status).append("\r\n");
        //构建响应头
        for (Map.Entry<String, String> entry: responseHead.entrySet()) {
            responseBuild.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
        }
        //添加Set-Cookie到响应头
        for (Map.Entry<String, String> entry: setCookie.entrySet()) {
            responseBuild.append("Set-Cookie: ").append(entry.getValue()).append("\r\n");
        }
        //构建分割行
        responseBuild.append("\r\n");
        //构建响应体
        responseBuild.append(bfOutputStream.getString());
        PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socketOutputStream, StandardCharsets.UTF_8));
        printWriter.write(responseBuild.toString());
        printWriter.flush();
    }

    @Override
    public void resetBuffer() {
    }

    @Override
    public boolean isCommitted() {
        return false;
    }

    @Override
    public void reset() {

    }

    @Override
    public void setLocale(Locale loc) {

    }

    @Override
    public Locale getLocale() {
        return null;
    }
}
